home *** CD-ROM | disk | FTP | other *** search
/ Hot Super Models / Hot Super Models.iso / unix / x11 / xv200.tar / xv-2.00 / xvpbm.c < prev    next >
C/C++ Source or Header  |  1992-01-02  |  11KB  |  479 lines

  1. /*
  2.  * xvpbm.c - load routine for 'pm' format pictures
  3.  *
  4.  * LoadPBM(fname, numcols)  -  loads a PBM, PGM, or PPM file
  5.  * WritePBM(fp,pic,w,h,r,g,b,numcols,style,raw,cmt)
  6.  */
  7.  
  8. /*
  9.  * Copyright 1989, 1990, 1991, 1992 by John Bradley and
  10.  *                       The University of Pennsylvania
  11.  *
  12.  * Permission to use, copy, and distribute for non-commercial purposes,
  13.  * is hereby granted without fee, providing that the above copyright
  14.  * notice appear in all copies and that both the copyright notice and this
  15.  * permission notice appear in supporting documentation.
  16.  *
  17.  * The software may be modified for your own purposes, but modified versions
  18.  * may not be distributed.
  19.  *
  20.  * This software is provided "as is" without any expressed or implied warranty.
  21.  *
  22.  * The author may be contacted via:
  23.  *    US Mail:   John Bradley
  24.  *               GRASP Lab, Room 301C
  25.  *               3401 Walnut St.
  26.  *               Philadelphia, PA  19104
  27.  *
  28.  *    Phone:     (215) 898-8813
  29.  *    EMail:     bradley@cis.upenn.edu
  30.  */
  31.  
  32.  
  33. #include "xv.h"
  34.  
  35.  
  36.  
  37. /* comments on error handling:
  38.    a truncated file is not considered a Major Error.  The file is loaded, the
  39.    rest of the pic is filled with 0's.
  40.  
  41.    a file with garbage characters in it is an unloadable file.  All allocated
  42.    stuff is tossed, and LoadPBM returns non-zero
  43.  
  44.    not being able to malloc is a Fatal Error.  The program is aborted. */
  45.  
  46.  
  47. #define TRUNCSTR "File appears to be truncated."
  48.  
  49. static int garbage;
  50. static long numgot, filesize;
  51.  
  52.  
  53. static int loadpbm(), loadpgm(), loadppm();
  54. static int getint(),  getbit(),  PBMerr();
  55.  
  56.  
  57. /*******************************************/
  58. int LoadPBM(fname,nc)
  59.      char *fname;
  60.      int   nc;
  61. /*******************************************/
  62. {
  63.   FILE  *fp;
  64.   int    c, c1;
  65.   int    w, h, maxv, rv;
  66.  
  67.   garbage = maxv = 0;
  68.  
  69.   /* open the stream, if necesary */
  70.   fp=fopen(fname,"r");
  71.   if (!fp) return 1;
  72.   
  73.   /* figure out the file size (for Informational Purposes Only) */
  74.   fseek(fp, 0L, 2);
  75.   filesize = ftell(fp);
  76.   fseek(fp, 0L, 0);
  77.  
  78.   /* read the first two bytes of the file to determine which format
  79.      this file is.  "P1" = ascii bitmap, "P2" = ascii greymap,
  80.      "P3" = ascii pixmap, "P4" = raw bitmap, "P5" = raw greymap,
  81.      "P6" = raw pixmap */
  82.  
  83.   c = getc(fp);  c1 = getc(fp);
  84.   if (c!='P' || c1<'1' || c1>'6') return(PBMerr("unknown format"));
  85.  
  86.   /* read in header information */
  87.   w = getint(fp);  h = getint(fp);
  88.  
  89.   /* if we're not reading a bitmap, read the 'max value' */
  90.   if ( !(c1=='1' || c1=='4')) {
  91.     maxv = getint(fp);
  92.     if (maxv < 1) garbage=1;    /* to avoid 'div by zero' probs */
  93.   }
  94.  
  95.  
  96.   if (garbage) {
  97.     if (fp!=stdin) fclose(fp);
  98.     return (PBMerr("Garbage characters in header."));
  99.   }
  100.  
  101.   rv = 0;
  102.  
  103.   if (c1=='1' || c1=='2' || c1=='3') SetDirRButt(F_FORMAT, F_PBMASCII);
  104.   else SetDirRButt(F_FORMAT, F_PBMRAW);
  105.  
  106.   /* call the appropriate subroutine to handle format-specific stuff */
  107.   if      (c1=='1' || c1=='4') rv = loadpbm(fp,w,h,       c1=='4' ? 1 : 0);
  108.   else if (c1=='2' || c1=='5') rv = loadpgm(fp,w,h, maxv, c1=='5' ? 1 : 0);
  109.   else if (c1=='3' || c1=='6') rv = loadppm(fp,w,h, maxv, c1=='6' ? 1 : 0, nc);
  110.  
  111.   if (fp!=stdin) fclose(fp);
  112.   return(rv);
  113. }  
  114.  
  115.  
  116.  
  117. /*******************************************/
  118. static int loadpbm(fp, w, h, raw)
  119. FILE *fp;
  120. int   w,h,raw;
  121. {
  122.   byte *pix;
  123.   int   i,j,bit;
  124.  
  125.  
  126.   SetDirRButt(F_COLORS, F_BWDITHER);
  127.  
  128.   SetISTR(ISTR_FORMAT,"PBM, %s format.  (%ld bytes)", 
  129.       (raw) ? "raw" : "ascii", filesize);
  130.   sprintf(formatStr, "%dx%d PBM.",w,h);
  131.  
  132.   /* load up the XV global variables */
  133.   pic = (byte *) calloc(w*h,1);
  134.   if (!pic) FatalError("couldn't malloc 'pic'");
  135.  
  136.   pWIDE = w;  pHIGH = h;
  137.  
  138.   /* B/W bitmaps have a two entry colormap */
  139.   r[0] = g[0] = b[0] = 255;   /* 0 = white */
  140.   r[1] = g[1] = b[1] = 0;     /* 1 = black */
  141.  
  142.   if (!raw) {
  143.     numgot = 0;
  144.     for (i=0, pix=pic; i<h; i++)
  145.       for (j=0; j<w; j++, pix++)
  146.     *pix = getbit(fp);
  147.  
  148.     if (numgot != w*h) PBMerr(TRUNCSTR);
  149.     if (garbage) {
  150.       free(pic);
  151.       return(PBMerr("Garbage characters in image data."));
  152.     }
  153.   }
  154.  
  155.  
  156.   else {   /* read raw bits */
  157.     int trunc = 0, k = 0;
  158.  
  159.     for (i=0, pix=pic; i<h; i++) {
  160.       if ((i&15)==0) WaitCursor();
  161.       for (j=0,bit=0; j<w; j++, pix++, bit++) {
  162.  
  163.     bit &= 7;
  164.     if (!bit) {
  165.       k = getc(fp);
  166.       if (k==EOF) { trunc=1; k=0; }
  167.     }
  168.  
  169.     *pix = (k&0x80) ? 1 : 0;
  170.     k = k << 1;
  171.       }
  172.     }
  173.  
  174.     if (trunc) PBMerr(TRUNCSTR);
  175.   }
  176.  
  177.   return 0;
  178. }
  179.  
  180.  
  181. /*******************************************/
  182. static int loadpgm(fp, w, h, maxv, raw)
  183. FILE *fp;
  184. int   w,h,maxv,raw;
  185. {
  186.   byte *pix;
  187.   int   i,j,bitshift;
  188.  
  189.   SetDirRButt(F_COLORS, F_GREYSCALE);
  190.  
  191.   SetISTR(ISTR_FORMAT,"PGM, %s format.  (%ld bytes)", 
  192.       (raw) ? "raw" : "ascii", filesize);
  193.   sprintf(formatStr, "%dx%d PGM.",w,h);
  194.  
  195.   /* load up the XV global variables */
  196.   pic = (byte *) calloc(w*h,1);
  197.   if (!pic) FatalError("couldn't malloc 'pic'");
  198.  
  199.   pWIDE = w;  pHIGH = h;
  200.  
  201.   /* if maxv>255, keep dropping bits until it's reasonable */
  202.   bitshift = 0;
  203.   while (maxv>255) { maxv = maxv>>1;  bitshift++; }
  204.  
  205.   /* fill in a greyscale colormap where maxv maps to 255 */
  206.   for (i=0; i<=maxv; i++)
  207.     r[i] = g[i] = b[i] = (i*255)/maxv;
  208.  
  209.   if (!raw) {
  210.     numgot = 0;
  211.     for (i=0, pix=pic; i<h; i++) {
  212.       if ((i&15)==0) WaitCursor();
  213.       for (j=0; j<w; j++, pix++)
  214.     *pix = (getint(fp) >> bitshift);
  215.     }
  216.   }
  217.  
  218.   else numgot = fread(pic, 1, w*h, fp);   /* read raw data */
  219.  
  220.   if (numgot != w*h) PBMerr(TRUNCSTR);
  221.  
  222.   if (garbage) {
  223.     free(pic);
  224.     return (PBMerr("Garbage characters in image data."));
  225.   }
  226.  
  227.   return 0;
  228. }
  229.  
  230.  
  231. /*******************************************/
  232. static int loadppm(fp, w, h, maxv, raw, nc)
  233. FILE *fp;
  234. int   w,h,maxv,raw,nc;
  235. {
  236.   byte *pix, *pic24, scale[256];
  237.   int   i,j,bitshift;
  238.  
  239.   SetDirRButt(F_COLORS, F_FULLCOLOR);
  240.  
  241.   SetISTR(ISTR_FORMAT,"PPM, %s format.  (%ld bytes)", 
  242.       (raw) ? "raw" : "ascii", filesize);
  243.   sprintf(formatStr, "%dx%d PPM.",w,h);
  244.  
  245.   /* allocate 24-bit image */
  246.   pic24 = (byte *) calloc(w*h*3,1);
  247.   if (!pic24) FatalError("couldn't malloc 'pic24'");
  248.  
  249.   /* if maxv>255, keep dropping bits until it's reasonable */
  250.   bitshift = 0;
  251.   while (maxv>255) { maxv = maxv>>1;  bitshift++; }
  252.  
  253.   if (!raw) {
  254.     numgot = 0;
  255.     for (i=0, pix=pic24; i<h; i++) {
  256.       if ((i&15)==0) WaitCursor();
  257.  
  258.       for (j=0; j<w*3; j++, pix++)
  259.     *pix = (getint(fp) >> bitshift);
  260.     }
  261.   }
  262.  
  263.   else numgot = fread(pic24, 1, w*h*3, fp);    /* read raw data */
  264.  
  265.   if (numgot != w*h*3) PBMerr(TRUNCSTR);
  266.  
  267.   if (garbage) {
  268.     free(pic24);
  269.     return(PBMerr("Garbage characters in image data."));
  270.   }
  271.  
  272.   /* have to scale all RGB values up (Conv24to8 expects RGB values to
  273.      range from 0-255 */
  274.  
  275.   if (maxv<255) { 
  276.     for (i=0; i<=maxv; i++) scale[i] = (i * 255) / maxv;
  277.  
  278.     for (i=0, pix=pic24; i<h; i++) 
  279.       for (j=0; j<w*3; j++, pix++) 
  280.     *pix = scale[*pix];
  281.   }
  282.  
  283.   i = Conv24to8(pic24,w,h,nc);
  284.   free(pic24);
  285.   return i;
  286. }
  287.  
  288.  
  289.  
  290. /*******************************************/
  291. static int getint(fp)
  292. FILE *fp;
  293. {
  294.   int c, i;
  295.  
  296.   /* skip forward to start of next number */
  297.   c = getc(fp);
  298.   while (1) {
  299.     /* eat comments */
  300.     if (c=='#') {   /* if we're at a comment, read to end of line */
  301.       while (c != '\n' && c != EOF) c=getc(fp);
  302.     }
  303.  
  304.     if (c==EOF) return 0;
  305.     if (c>='0' && c<='9') break;   /* we've found what we were looking for */
  306.  
  307.     /* see if we are getting garbage (non-whitespace) */
  308.     if (c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=',') garbage=1;
  309.  
  310.     c = getc(fp);
  311.   }
  312.  
  313.  
  314.   /* we're at the start of a number, continue until we hit a non-number */
  315.   i = 0;
  316.   while (1) {
  317.     i = (i*10) + (c - '0');
  318.     c = getc(fp);
  319.     if (c==EOF) return i;
  320.     if (c<'0' || c>'9') break;
  321.   }
  322.  
  323.   numgot++;
  324.   return i;
  325. }
  326.  
  327.  
  328.  
  329. /*******************************************/
  330. static int getbit(fp)
  331. FILE *fp;
  332. {
  333.   int c;
  334.  
  335.   /* skip forward to start of next number */
  336.   c = getc(fp);
  337.   while (1) {
  338.     /* eat comments */
  339.     if (c=='#') {   /* if we're at a comment, read to end of line */
  340.       while (c != '\n' && c != EOF) c=getc(fp);
  341.     }
  342.  
  343.     if (c==EOF) return 0;
  344.     if (c=='0' || c=='1') break;   /* we've found what we were looking for */
  345.  
  346.     /* see if we are getting garbage (non-whitespace) */
  347.     if (c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=',') garbage=1;
  348.  
  349.     c = getc(fp);
  350.   }
  351.  
  352.  
  353.   numgot++;
  354.   return(c-'0');
  355. }
  356.  
  357.  
  358. /*******************************************/
  359. static int PBMerr(st)
  360. char *st;
  361. {
  362.   SetISTR(ISTR_WARNING,st);
  363.   return 1;
  364. }
  365.  
  366.  
  367.  
  368.  
  369.  
  370. /*******************************************/
  371. int WritePBM(fp,pic,w,h,rmap,gmap,bmap,numcols,colorstyle,raw)
  372. FILE *fp;
  373. byte *pic;
  374. int   w,h;
  375. byte *rmap, *gmap, *bmap;
  376. int   numcols, colorstyle, raw;
  377. {
  378.   /* writes a PBM/PGM/PPM file to the already open stream
  379.      if (raw), writes as RAW bytes, otherwise writes as ASCII 
  380.      'colorstyle' single-handedly determines the type of file written
  381.      if colorstyle==0, (Full Color) a PPM file is written
  382.      if colorstyle==1, (Greyscale)  a PGM file is written
  383.      if colorstyle==2, (B/W stipple) a PBM file is written */
  384.  
  385.   int   magic;
  386.   byte *pix;
  387.   int   i,j,len;
  388.  
  389.   /* calc the appropriate magic number for this file type */
  390.   magic = 0;
  391.   if      (colorstyle==0) magic = 3;
  392.   else if (colorstyle==1) magic = 2;
  393.   else if (colorstyle==2) magic = 1;
  394.  
  395.   if (raw && magic) magic+=3;
  396.  
  397.   if (!magic) return(PBMerr("WritePBM: unknown file format"));
  398.  
  399.   /* write the header info */
  400.   fprintf(fp,"P%d\n",magic);
  401.   fprintf(fp,"# created by 'xv %s'\n", namelist[curname]);
  402.   fprintf(fp,"%d %d\n",w,h);
  403.   if (colorstyle!=2) fprintf(fp,"255\n");
  404.  
  405.   if (ferror(fp)) return -1;
  406.  
  407.   /* write the image data */
  408.  
  409.   if (colorstyle==0) {                  /* 24bit RGB, 3 bytes per pixel */
  410.     for (i=0, pix=pic, len=0; i<h; i++) {
  411.       if ((i&15)==0) WaitCursor();
  412.       for (j=0; j<w; j++,pix++) {
  413.     if (raw) {
  414.       putc(r[*pix],fp);  
  415.       putc(g[*pix],fp);  
  416.       putc(b[*pix],fp);
  417.     }
  418.     else {
  419.       fprintf(fp,"%3d %3d %3d ",r[*pix], g[*pix], b[*pix]);
  420.       len+=12;
  421.       if (len>58) { fprintf(fp,"\n");  len=0; }
  422.     }
  423.       }
  424.     }
  425.   }
  426.  
  427.   else if (colorstyle==1) {             /* 8-bit greyscale */
  428.     byte rgb[256];
  429.     for (i=0; i<numcols; i++) rgb[i] = MONO(rmap[i],gmap[i],bmap[i]);
  430.     for (i=0, pix=pic, len=0; i<w*h; i++,pix++) {
  431.       if ((i&0x7fff)==0) WaitCursor();
  432.       if (raw) putc(rgb[*pix],fp);
  433.       else {
  434.     fprintf(fp,"%3d ",rgb[*pix]);
  435.     len += 4;
  436.     if (len>66) { fprintf(fp,"\n");  len=0; }
  437.       }
  438.     }
  439.   }
  440.  
  441.   else if (colorstyle==2) {             /* 1-bit B/W stipple */
  442.     int bit,k;
  443.     for (i=0, pix=pic, len=0; i<h; i++) {
  444.       if ((i&15)==0) WaitCursor();
  445.       for (j=0, bit=0, k=0; j<w; j++, pix++) {
  446.     if (raw) {
  447.       k = (k << 1) | *pix;
  448.       bit++;
  449.       if (bit==8) {
  450.         fputc(~k,fp);
  451.         bit = k = 0;
  452.       }
  453.     }
  454.     else {
  455.       if (*pix) fprintf(fp,"0 ");
  456.            else fprintf(fp,"1 ");
  457.       len+=2;
  458.       if (len>68) { fprintf(fp,"\n"); len=0; }
  459.     }
  460.       } /* j */
  461.       if (raw && bit) {
  462.     k = k << (8-bit);
  463.     fputc(~k,fp);
  464.       }
  465.     }
  466.   }
  467.  
  468.   if (ferror(fp)) return -1;
  469.  
  470.   return 0;
  471. }
  472.  
  473.  
  474.       
  475.       
  476.  
  477.  
  478.  
  479.